/*
 * Common API for all pages
 */
REST_API_PREFIX="/symdb/products/"
function fnGetProductRestPrefix() {
	var product = $.url().param('product');
	var version = $.url().param('version');

	if (!product) {
		product = "ohos_rk3568";
		version = "3.2.6.5";
	}
	return REST_API_PREFIX + product + "/" + version + "/";
}

function redirectToDefaultProduct() {
	$.get("/symdb/products", function (data, status) {
		var products = JSON.parse(data)["data"];

		window.location = fnGetStaticHtmlUrl("modules", products[0][1], products[0][2]);
	});
}

var tableOptions = {
	"deps_dialog": {
		"title": "依赖关系列表",
		"buttons": [{
			"id": "download_xml_deps", "name": "XML下载"
		}, {
			"id": "download_svg_deps", "name": "SVG下载"
		}, {
			"id": "download_png_deps", "name": "PNG下载"
		}, {
			"id": "download_dot_deps", "name": "GraphViz文件下载"
		}],
		"table": {
			"id": "depends",
			"cols": ["Id", "CallerId", "CalleeId", "调用部件", "调用模块", "被调用部件", "被调用模块", "依赖类型", "调用次数"]
		}
	},
	"help_info_dialog": {
		"title": "帮助信息",
		"extra": {
			"class": "help_modal",
			"style": "transform: translateX(-50%) translateY(-50%)"
		},
		"wrapper": {
			"id": "help_info_img",
			"type": "img"
		}
	},
	"module_dialog": {
		"title": "模块详细信息",
		"wrapper": {
			"id": "accordion",
			"type": "div"
		}
	},
	"param_dialog": {
		"title": "参数详细信息",
		"wrapper": {
			"id": "accordion_param_dialog",
			"type": "div"
		}
	},
	"stage_cmd_dialog": {
		"title": "阶段执行命令信息",
		"wrapper": {
			"id": "accordion_stage_cmd_dialog",
			"type": "div"
		}
	},
	"stage_service_dialog": {
		"title": "阶段启动服务信息",
		"wrapper": {
			"id": "accordion_stage_service_dialog",
			"type": "div"
		}
	},
	"param_limits_dialog": {
		"title": "DAC MAC 查询",
		"wrapper": {
			"id": "accordion_limits_dialog",
			"type": "div"
		}
	},
	"param_config_dialog": {
		"title": "新增参数配置查询",
		"wrapper": {
			"id": "accordion_config_dialog",
			"type": "div"
		}
	},
	"service_dialog": {
		"title": "SERVICE 详细信息",
		"wrapper": {
			"id": "accordion_service_dialog",
			"type": "div"
		}
	},
	"service_socket_dialog": {
		"title": "SERVICE SOCKET详细信息",
		"wrapper": {
			"id": "accordion_service_socket_dialog",
			"type": "div"
		}
	},
	"callinfo_dialog": {
		"title": "调用详情",
		"buttons": [{
			"id": "download_xml_callinfo", "name": "XML下载"
		}],
		"table": {
			"id": "callinfo_table",
			"cols": ["调用者", "提供者", "函数名"]
		}
	},
	"symbol_dialog": {
		"title": "符号信息",
		"buttons": [{
			"id": "download_xml_symbols", "name": "XML下载"
		}],
		"table": {
			"id": "symbol_table",
			"cols": ["调用者", "提供者", "函数名"]
		}
	},
	"processes_dialog": {
		"title": "进程信息",
		"buttons": [{
			"id": "download_xml_processes", "name": "XML下载"
		}],
		"table": {
			"id": "processes_table",
			"cols": ["ID", "pid", "Name", "Process", "VMA", "Size", "Rss", "Pss", "Swap", "SwapPss", "Shared_Clean", "Shared_Dirty", "Private_Clean", "Private_Dirty", "Referenced", "Anonymous", "LazyFree", "KernelPageSize", "MMUPageSize", "AnonHugePages", "ShmemPmdMapped", "Shared_Hugetlb", "Private_Hugetlb", "Locked", "THPeligible", "FilePmdMapped"]
		}
	},
	"vmas_dialog": {
		"title": "VMA信息",
		"buttons": [{
			"id": "download_xml_vmas", "name": "XML下载"
		}],
		"table": {
			"id": "vmas_table",
			"cols": ["ID", "Process", "Name", "Start", "End", "Permission", "Offset", "Dev", "Idx", "Size", "Rss", "Pss", "Swap", "SwapPss", "Shared_Clean", "Shared_Dirty", "Private_Clean", "Private_Dirty", "Referenced", "Anonymous", "LazyFree", "KernelPageSize", "MMUPageSize", "AnonHugePages", "ShmemPmdMapped", "Shared_Hugetlb", "Private_Hugetlb", "Locked", "THPeligible", "FilePmdMapped"]
		}
	},
	"objects_dialog": {
		"title": "加载对象信息",
		"buttons": [{
			"id": "download_xml_objects", "name": "XML下载"
		}],
		"table": {
			"id": "objects_table",
			"cols": ["ID", "Process", "Name", "VMA", "Size", "Rss", "Pss", "Swap", "SwapPss", "Shared_Clean", "Shared_Dirty", "Private_Clean", "Private_Dirty", "Referenced", "Anonymous", "LazyFree", "KernelPageSize", "MMUPageSize", "AnonHugePages", "ShmemPmdMapped", "Shared_Hugetlb", "Private_Hugetlb", "Locked", "THPeligible", "FilePmdMapped"]
		}
	},
	"threads_dialog": {
		"title": "线程信息",
		"buttons": [{
			"id": "download_xml_threads", "name": "XML下载"
		}],
		"table": {
			"id": "threads_table",
			"cols": ["TID", "线程名", "PID", "进程名"]
		}
	},
	"symbol_calls_cnt": {
		"title": "符号调用信息",
		"buttons": [{
			"id": "download_xml_symbol_calls_cnt", "name": "XML下载"
		}],
		"table": {
			"id": "symbol_calls_cnt_table",
			"cols": ["符号ID", "模块ID", "符号名称", "demangle", "提供模块", "被调用次数"]
		}
	},
	"symbol_calls_details": {
		"title": "符号调用信息",
		"buttons": [{
			"id": "download_xml_symbol_calls_details", "name": "XML下载"
		}],
		"table": {
			"id": "symbol_calls_details_table",
			"cols": ["符号ID", "callee_id", "caller_id", "符号名称", "demangle", "提供模块", "调用模块"]
		}
	},
};

function _createDialogHeader(dialogId) {
	var content = '<div class="modal-header">\n';
	content += '<h5 class="modal-title">' + tableOptions[dialogId]["title"] + '</h5>\n';
	content += '<button type="button" class="close" data-dismiss="dialog" aria-label="Close" id="' + dialogId + '_close_btn"value="' + dialogId + '">\n';
	content += '<span aria-hidden="true">&times;</span>\n';
	content += '</button>\n';
	content += '</div>\n';
	return content;
}

function _createDialogButtons(dialogId) {
	if (!("buttons" in tableOptions[dialogId])) {
		return "";
	}
	var content = '<div class="btn-group me-2 float-end">\n';
	tableOptions[dialogId]["buttons"].forEach(function (btn, idx, arr) {
		content += '<button type="button" id="' + btn["id"] + '" class="btn btn-sm btn-outline-secondary">' + btn["name"] + '</button>\n';
	});
	content += '</div>\n';
	return content;
}

function _createDialogTables(dialogId) {
	if (!("table" in tableOptions[dialogId])) {
		return "";
	}

	var content = '<table cellpadding="0" cellspacing="0" border="0" class="display" id="' + tableOptions[dialogId]["table"]["id"] + '">\n';
	content += '<thead>\n<tr>\n';

	tableOptions[dialogId]["table"]["cols"].forEach(function (th, idx, arr) {
		content += '<th class="show_in_line">' + th + '</th>\n';
	});
	content += '</tr>\n</thead>\n';
	content += '<tbody>\n';
	content += '</tbody>\n';
	content += '</table>\n';

	return content;
}

function _createWrapperBlock(dialogId) {
	if (!("wrapper" in tableOptions[dialogId])) {
		return "";
	}

	return '<' + tableOptions[dialogId]["wrapper"]["type"] + ' id="' + tableOptions[dialogId]["wrapper"]["id"] + '">\n';
}

function _createDialogDiv(dialogId) {
	if (!("extra" in tableOptions[dialogId])) {
		return '<div class="modal-dialog modal-lg" role="document">\n';
	}
	var extra = tableOptions[dialogId]["extra"];
	var content = '<div class="modal-dialog modal-lg';

	if ("class" in extra) {
		content += " " + extra["class"];
	}

	content += '" role="document"';
	if ("style" in extra) {
		content += ' style="' + extra["style"] + '"';
	}

	content += '>\n';
	return content;
}

function createDialogWithTable(dialogId) {
	if (!(dialogId in tableOptions)) {
		return;
	}

	var content = _createDialogDiv(dialogId);
	content += '<div class="modal-content">\n';

	// Header
	content += _createDialogHeader(dialogId);

	// Body
	content += '<div class="modal-body">\n';

	//   wrapper item
	content += _createWrapperBlock(dialogId);

	//   buttons
	content += _createDialogButtons(dialogId);

	//   table
	content += _createDialogTables(dialogId);

	content += '</div>\n';

	// Footer
	content += '<div class="modal-footer">\n';
	content += '</div>\n';

	content += '</div>\n';
	content += '</div>\n';

	$("#"+dialogId).html(content);

	$("#"+dialogId+"_close_btn").click(function(evt) {
		var dialogId = $(evt.target).parent().val();
		$("#"+dialogId).modal("hide");
	});
}

function createProductMenus(currentPage) {
	$.get("/symdb/products", function (data, status) {
		var products = JSON.parse(data)["data"];

		var curProduct = $.url().param('product');
		var curVersion = $.url().param('version');

		// Add dropdown menu button
		menuHtml = '<button id="current_product_btn" class="btn dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown">';
		if (!curProduct) {
			curProduct = products[1];
			curVersion = products[2];
		}
		menuHtml += curProduct + '/' + curVersion + '</button>\n';

		//$("#current_product_btn").text("test/test");
		var lastProduct = "";
		products.forEach(function (product, idx, arr) {
			if ((lastProduct === "") || (lastProduct != product[1])) {
				// End last product menu
				if (lastProduct === "") {
					menuHtml += '<ul class="dropdown-menu text-small">\n';
				} else {
					menuHtml += '</ul></li>\n';
				}
				// Add a new product menu
				menuHtml += '<li><a class="dropdown-item">' + product[1] + '&raquo;</a><ul class="dropdown-menu dropdown-submenu">\n';
				lastProduct = product[1];
			}

			// Add a product version submenu
			menuHtml += '<li><a class="dropdown-item" href="' + fnGetStaticHtmlUrl(currentPage, product[1], product[2]) + '">' + product[2] + '</a></li>\n';
		});
		// End last product
		menuHtml += '</ul></li></ul>\n';

		$("#products_menu").html(menuHtml);
	});
}

function  createSubPageMenus(currentPage, subpages) {
	var htmlContent = "";
	for (const [key, val] of Object.entries(subpages)) {
		var activeStr = "";
		if (currentPage === key) {
			activeStr = " btn-secondary";
		}
		//htmlContent += '<li class="nav-item' + activeStr +'" href="' + fnGetStaticHtmlUrl(key) + '">' + val + '</li>\n';
		htmlContent += '<li class="nav-item"><a class="btn btn-sm' + activeStr + '" href="' + fnGetStaticHtmlUrl(key) + '">' + val + '</a></li>\n';
	}
	$("#subpages_menu").html(htmlContent);
}

$(function createTopMenus() {
	var pages = {
		"modules": {"name": "模块列表"},
		"components": {"name": "部件列表"},
		"parameters": {"name": "系统参数"},
		"startup_configs": {"name": "启动配置信息", "subpages": {"startup_configs": "系统服务", "startup_config_jobs": "系统启动过程"}},
		"chipsetsdk": {"name": "看护模块", "subpages": {"chipsetsdk": "Chipset SDK", "platformsdk": "Platform SDK", "innerapi": "Inner API"}},
		"symbols_dup": {"name": "符号分析", "subpages": {"symbols_dup": "重复定义符号", "symbols_search": "符号搜索"}},
		"processes": {"name": "内存信息", "subpages": {"processes": "进程内存", "objects": "模块内存", "threads": "线程信息"}},
		"help": {"name": "帮助"}
	};
	var currentPage = $.url().attr('file');
	if (currentPage === "") {
		currentPage = "modules.html"
	}
	currentPage = currentPage.substring(0, currentPage.indexOf(".html"));

	var htmlContent = "";
	for (const [key, val] of Object.entries(pages)) {
		var activeStr = "";
		if (currentPage === key) {
			activeStr = " active";
		} else if ("subpages" in val) {
			for (const [subpage, subname] of Object.entries(val["subpages"])) {
				if (currentPage === subpage) {
					activeStr = " active";
					break;
				}
			}
		}
		htmlContent += '<li class="nav-item"><a href="' + fnGetStaticHtmlUrl(key) + '" class="nav-link' + activeStr + '">' + val["name"] + '</a></li>\n';

		if ("subpages" in val && currentPage in val["subpages"]) {
			createSubPageMenus(currentPage, val["subpages"]);
		}
	};
	$("#pages_menu").html(htmlContent);

	createProductMenus(currentPage);

	$(".close").click(function(evt) {
		//console.log($(evt.target).parent());
		dialogId = $(evt.target).parent().val();
		$("#"+dialogId).modal("hide");
		//$(".modal").modal("hide");
	});
});

function fnArgsToURI(args) {
	var str = [];
	for(var p in args) {
		str.push(encodeURIComponent(p) + "=" + encodeURIComponent(args[p]));
	}
	return str.join("&");
}

function fnGetStaticHtmlUrl(name, product, version, xargs) {
	if (xargs) {
		args = xargs;
	} else {
		args = {};
	}
	if (product && version) {
		args["product"] = product;
		args["version"] = version;
	} else {
		args["product"] = $.url().param('product');
		args["version"] = $.url().param('version');
	}
	return "/" + name + ".html?" + fnArgsToURI(args);
}

function fnGetAllItemsFilterUrl(name, xargs) {
	prefix = fnGetProductRestPrefix();
	url =  prefix + name;

	if (xargs) {
		args = xargs;
	} else {
		args = {};
	}
	var params = $.url().param();
	for (const [key, val] of Object.entries(params)) {
		if (!["product", "version", "_"].includes(key)) {
			args[key] = val
		}
	};
	if (Object.keys(args).length > 0) {
		return url + "?" + fnArgsToURI(args);
	}
	return url;
}

function humanFileSize(size) {
		var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
		return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}

/*
 * Data Table Column Filter Related API
 */
(function($) {
/*
 * Function: fnGetColumnData
 * Purpose:  Return an array of table values from a particular column.
 * Returns:  array string: 1d data array 
 * Inputs:   object:oSettings - dataTable settings object. This is always the last argument past to the function
 *				   int:iColumn - the id of the column to extract the data from
 *				   bool:bUnique - optional - if set to false duplicated values are not filtered out
 *				   bool:bFiltered - optional - if set to false all the table data is used (not only the filtered)
 *				   bool:bIgnoreEmpty - optional - if set to false empty values are not filtered from the result array
 */
$.fn.dataTableExt.oApi.fnGetColumnData = function ( oSettings, iColumn, bUnique, bFiltered, bIgnoreEmpty ) {
	// check that we have a column id
	if ( typeof iColumn == "undefined" ) return new Array();

	// by default we only wany unique data
	if ( typeof bUnique == "undefined" ) bUnique = true;

	// by default we do want to only look at filtered data
	if ( typeof bFiltered == "undefined" ) bFiltered = true;

	// by default we do not wany to include empty values
	if ( typeof bIgnoreEmpty == "undefined" ) bIgnoreEmpty = true;

	// list of rows which we're going to loop through
	var aiRows;

	// use only filtered rows
	if (bFiltered == true) aiRows = oSettings.aiDisplay;
	// use all rows
	else aiRows = oSettings.aiDisplayMaster; // all row numbers

	// set up data array
	var asResultData = new Array();

	for (var i=0,c=aiRows.length; i<c; i++) {
		iRow = aiRows[i];
		var aData = this.fnGetData(iRow);
		var sValue = aData[iColumn];

		// ignore empty values?
		if (bIgnoreEmpty == true && sValue.length == 0) continue;

		// ignore unique values?
		else if (bUnique == true && jQuery.inArray(sValue, asResultData) > -1) continue;

		// else push the value onto the result data array
		else asResultData.push(sValue);
	}

	return asResultData;
}}(jQuery));

function fnCreateSelect( aData ) {
	var r='<select><option value=""></option>', i;
	var iLen = aData.length;
	for ( i=0 ; i<iLen ; i++ ) {
		r += '<option value="'+aData[i]+'">'+aData[i]+'</option>';
	}
	return r+'</select>';
}

/*
 * Modules related API
 */

function fnModuleCommonRowCallback(aData, nRow) {
	/* Human readble size */
	$('td:eq(23)', nRow).text( humanFileSize(aData[25]) );
}

function fnModuleTableCommonProc(moduleTable, selectProc) {
	$("#modules tbody").on("click", "tr", function() {
		if ($(this).hasClass('selected')) {
			$(this).removeClass('selected');
		} else {
			moduleTable.$('tr.selected').removeClass('selected');
			$(this).addClass('selected');
		}

		if (selectProc) {
			selectProc(moduleTable.fnGetData(this));
		}
	});
}

function fnGetModulesRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();

	// Handle different API path formats for FastAPI version
	if (cmd === "details") {
		url = prefix + "modules/" + id + "/details";
	} else if (cmd === "fields") {
		url = prefix + "modules/" + id + "/fields";
	} else {
		// For other commands, use the original format
		url = prefix + "modules/" + id + "/" + cmd;
	}

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnGetDepsRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();

	// For FastAPI version, dependencies are accessed through modules endpoint
	url = prefix + "deps/" + id + "/symbols";

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnEvtShowCallTables(id, type) {
	createDialogWithTable("symbol_dialog");

	var url = fnGetModulesRestUrl(id, "fields", {"type":type});
	var symbolTable = $('#symbol_table').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true
	} );
	$('#download_xml_symbols').unbind ('click').click(id, function (evt) {
		window.open(fnGetModulesRestUrl(evt.data, "fields", {"type":type, "format":"xml"}));
	});
	$('#symbol_dialog').appendTo("body").modal("show");
}

function fnEvtShowSymbolsForDeps(id) {
	createDialogWithTable("callinfo_dialog");

	var url = fnGetDepsRestUrl(id, "symbols");
	var symbolTable = $('#callinfo_table').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true
	} );
	$('#download_xml_callinfo').unbind ('click').click(id, function (evt) {
		window.open(fnGetDepsRestUrl(evt.data, "symbols", {"format":"xml"}));
	});
	$('#callinfo_dialog').appendTo("body").modal("show");
}

function fnEvtShowDepsTables(id, type) {
	createDialogWithTable("deps_dialog");

	url = fnGetModulesRestUrl(id, "fields", {"type": type});
	var symbolTable = $('#depends').dataTable( {
		"bProcessing": true,
		"sScrollX": "1000px",
		"pageLength": 15,
		"bPaginate": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"columnDefs": [{
			visible: false,
			targets: [0,1,2],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			/* Append the grade to the default row class name */
			dataToLink = aData[8];
			if (dataToLink > 0) {
				$('td:eq(5)', nRow).html( '<a href="javascript:fnEvtShowSymbolsForDeps(' + aData[0] + ')">' + dataToLink + '</a>' );
			}

			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[1] + '\')">' + aData[4] + '</a>';
			$('td:eq(1)', nRow).html(link);

			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[2] + '\')">' + aData[6] + '</a>';
			$('td:eq(3)', nRow).html(link);
			return nRow;
		}
	} );
	$('#download_xml_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetModulesRestUrl(evt.data, "fields", {"type":type, "format":"xml", "details":1}));
	});
	$('#download_svg_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetModulesRestUrl(evt.data, "fields", {"type":type, "format":"svg"}));
	});
	$('#download_png_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetModulesRestUrl(evt.data, "fields", {"type":type, "format":"png"}));
	});
	$('#download_dot_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetModulesRestUrl(evt.data, "fields", {"type":type, "format":"dot"}));
	});
	$('#deps_dialog').appendTo("body").modal("show");

	setTimeout(function() {
		$("#depends").attr("style", "width:100%");
	}, 10);
}

function fnShowHelpInfo(type) {
	createDialogWithTable("help_info_dialog");
	$("#help_info_img").attr("src", "/images/" + type);
	$('#help_info_dialog').appendTo("body").modal("show");
}

function fnEvtFuncCallGraph (rowData, category) {
	var module_id = rowData[0];

	xargs = {"type":"deps", "format":"svg"};
	if (category) {
		xargs["__category"] = category;
	}
	$("#svg_callgraph").attr("data", fnGetModulesRestUrl(module_id, "fields", xargs));
}

var groupDict = {
	"publicapi": "公共API模块",
	"innerapi_chc": "跨组件Inner API模块",
	"innerapi_cc": "跨部件Inner API模块",
	"innerapi_chc_indirect": "跨组件间接依赖模块",
	"innerapi_cc_indirect": "跨部件间接依赖模块",
	"pentry": "进程入口模块",
	"private": "组件内私有模块"
};

var hdiTypeDict = {
	"hdi_proxy": "HDI Proxy模块",
	"hdi_stub": "HDI Stub模块",
	"hdi_pass": "HDI直通模块",
	"hdi_service": "HDI服务模块"
};

var total_colums = 42;
var hidden_cols = 2;

var select_types = ["content", "range", "list", "dict"];
var filterDict = {
	"subsystem_footer": {"idx": hidden_cols + 0, "type": "content"},
	"component_footer": {"idx": hidden_cols + 1, "type": "edit"},
	"module_footer": {"idx": hidden_cols + 2, "type": "edit"},
	"group_footer": {"idx": hidden_cols + 3, "type": "dict", "dict": groupDict},
	"deps_footer": {"idx": hidden_cols + 5, "type": "range", "range": [{"val":0}, {"min":0}, {"min":0, "max":10}, {"min":10}]},
	"dependedBy_footer": {"idx": hidden_cols + 10, "type": "range", "range": [{"val":0}, {"min":0}, {"min":0, "max":10}, {"min":10}]},
	"dependedBy_external_footer": {"idx": hidden_cols + 11, "type": "range", "range": [{"val":0}, {"min":0}, {"min":0, "max":10}, {"min":10}]},

	// Indexing from last
	"third_party_footer": {"idx": total_colums - hidden_cols - 7, "type": "list", "list": [0,1]},
	"sa_footer": {"idx": total_colums - hidden_cols - 6, "type": "range", "range": [{"val":0}, {"min":0}]},
	"napi_footer": {"idx": total_colums - hidden_cols - 5, "type": "list", "list": [0,1]},
	"chipset_footer": {"idx": total_colums - hidden_cols - 4, "type": "list", "list": [0,1]},
	"hdiType_footer": {"idx": total_colums - hidden_cols - 3, "type": "dict", "dict": hdiTypeDict},
	"innerapi_footer": {"idx": total_colums - hidden_cols - 2, "type": "list", "list": [0,1]},
	"platformsdk_footer": {"idx": total_colums - hidden_cols - 1, "type": "list", "list": [0,1]},
	"chipsetsdk_footer": {"idx": total_colums - hidden_cols, "type": "list", "list": [0,1]},
};

function matchWithRange(val, range) {
	//console.log("match " + val + " with range: " + getRangeName(range));
	if ("val" in range) {
		if (val == range["val"]) {
			return true;
		}
		return false;
	} else if ("min" in range) {
		if ("max" in range) {
			if ((val > range["min"]) && (val < range["max"])) {
				return true;
			}
			return false;
		}
		if (val > range["min"]) {
			return true;
		}
		return false;
	} else if ("max" in range) {
		if (val < range["max"]) {
			return true;
		}
		return false;
	}
	return true;
}

function dataMatchWithFilterDict(data, ele, filter) {
	if (select_types.includes(filter["type"])) {
		ele = ele + " select";
	} else {
		ele = ele + " input";
	}
	var filterVal = $(ele).val();
	if (filterVal === undefined || (filterVal === "")) {
		//console.log(ele + ": [" + filterVal + "] no need filter");
		return true;
	}
	if (filter["type"] == "range") {
		if (filterVal == 0 || filterVal === "0") {
			return true;
		}
		return matchWithRange(data[filter["idx"]], filter["range"][filterVal - 1]);
	}
	if (select_types.includes(filter["type"])) {
		if (data[filter["idx"]] === filterVal) {
			return true;
		}
		return false;
	}
	if (!data[filter["idx"]].includes(filterVal)) {
		//console.log("filter val [" + filterVal + " not matched.");
		return false;
	}
	return true;
}

function getRangeName(range) {
	if ("val" in range) {
		return range["val"];
	} else if ("min" in range) {
		if ("max" in range) {
			return range["min"] + "-" + range["max"];
		}
		return ">" + range["min"];
	} else if ("max" in range) {
		return "<" + range["max"];
	}
	return "";
}

function fnCreateRangeSelect(filter) {
	var r='<select><option value=></option>';
	filter["range"].forEach(function (val, idx, arr) {
		idx = idx + 1;
		r += '<option value=' + idx + '>' + getRangeName(val) + '</option>';
	});
	return r+'</select>';
}

function fnCreateListSelect(filter) {
	var r='<select><option value=></option>';
	filter["list"].forEach(function (val, idx, arr) {
		r += '<option value=' + val + '>' + val + '</option>';
	});
	return r+'</select>';
}

function fnCreateDictSelect(filter) {
	var r='<select><option value=></option>';
	for (val in filter["dict"]) {
		r += '<option value="' + val + '">' + filter["dict"][val] + '</option>';
	};
	return r+'</select>';
}

function createStaticFilterFooters(moduleTable) {
	$.fn.dataTable.ext.search.push(function (settings, data, dataIndex) {
		if (settings.sTableId != "modules") {
			return true;
		}
		for (var ele_id in filterDict) {
			var ele = '#' + ele_id;
			filter = filterDict[ele_id];
			if (!dataMatchWithFilterDict(data, ele, filter)) {
				return false;
			}
		}
		return true;
	});

	for (var ele_id in filterDict) {
		var ele = '#' + ele_id;
		filter = filterDict[ele_id];
		if (filter["type"] == "edit") {
			$(ele).html('<input type="text">');
			$("input", ele).keyup( function () {
				moduleTable.fnDraw();
			} );
			continue;
		}
		if (filter["type"] == "range") {
			$(ele).html(fnCreateRangeSelect(filter));
			$("select", ele).change( function () {
				moduleTable.fnDraw();
			} );
			continue;
		}
		if (filter["type"] == "list") {
			$(ele).html(fnCreateListSelect(filter));
			$("select", ele).change( function () {
				moduleTable.fnDraw();
			} );
			continue;
		}
		if (filter["type"] == "dict") {
			$(ele).html(fnCreateDictSelect(filter));
			$("select", ele).change( function () {
				moduleTable.fnDraw();
			} );
			continue;
		}
	};
}

function createDynamicFilterFooters(moduleTable) {
	window.setTimeout( function () {
		for (var ele_id in filterDict) {
			var ele = '#' + ele_id;
			filter = filterDict[ele_id];
			if (filter["type"] != "content") {
				continue;
			}
			$(ele).html(fnCreateSelect( moduleTable.fnGetColumnData(filter["idx"]) ));
			$('select', $(ele)).change( function () {
				moduleTable.fnDraw();
			} );
		}
	}, 1500);
}

var details_dict = {
	"basic_info": {
		"name": "基础信息",
		"rows": [{
			"key": "path",
			"name": "模块路径"
		}, {
			"key": "componentName",
			"name": "归属部件"
		}, {
			"key": "subsystem",
			"name": "归属子系统"
		}, {
			"key": "labelPath",
			"name": "编译路径"
		}, {
			"key": "chipset",
			"name": "归属组件"
		}, {
			"key": "modGroup",
			"name": "模块类型"
		}, {
			"key": "third_party",
			"name": "是否三方库"
		}, {
			"key": "innerapi",
			"name": "是否Inner API"
		}, {
			"key": "innerapi_declared",
			"name": "是否申明Inner API"
		}, {
			"key": "innerapi_tags",
			"name": "Inner API类型标记"
		}, {
			"key": "right_tags",
			"name": "正确的Inner API类型标记"
		}, {
			"key": "platformsdk",
			"name": "是否Platform SDK模块"
		}, {
			"key": "chipsetsdk",
			"name": "是否Chipset SDK模块"
		}, {
			"key": "sa_id",
			"name": "SA ID"
		}, {
			"key": "hdiType",
			"name": "HDI模块类型"
		}, {
			"key": "version_script",
			"name": "符号隐藏"
		}]
	},
	"resource_info": {
		"name": "ROM&RAM消耗",
		"rows": [{
			"key": "size",
			"name": ["ROM", "文件大小"]
		}, {
			"key": "bss_size",
			"name": ["ROM", "bss段大小"]
		}, {
			"key": "data_size",
			"name": ["ROM", "data段大小"]
		}, {
			"key": "processes",
			"name": ["RAM", "被加载的进程数"]
		}, {
			"key": "Pss",
			"name": ["RAM", "Pss内存信息"]
		}, {
			"key": "swapPss",
			"name": ["RAM", "Pss内存信息"]
		}, {
			"key": "Shared_Dirty",
			"name": ["RAM", "Shared_Dirty内存信息"]
		}, {
			"key": "Private_Dirty",
			"name": ["RAM", "Pss内存信息"]
		}]
	},
	"deps_info": {
		"name": "依赖信息",
		"rows": [{
			"name": ['<a href="javascript:fnShowHelpInfo(\'deps.png\')">详细定义</a>', "英文", "含义", "数值"]
		}, {
			"key": "deps",
			"name": ["D(n)", "deps", "直接依赖模块个数"]
		}, {
			"key": "deps_indirect",
			"name": ["D_I(n)", "deps_indirect", "间接依赖模块个数"]
		}, {
			"key": "deps_total",
			"name": ["D_T(n)", "deps_total", "依赖模块总个数"]
		}, {
			"key": "depth",
			"name": ["D_D", "deps_depth", "依赖深度"]
		}, {
			"key": "deps_external",
			"name": ["D_e(n)", "deps_external", "依赖其它部件模块数"]
		}, {
			"key": "deps_internal",
			"name": ["D_n(n)", "deps_internal", "依赖本部件模块数"]
		}]
	},
	"dependedBy_info": {
		"name": "被依赖信息",
		"rows": [{
			"name": ['<a href="javascript:fnShowHelpInfo(\'dependedBy.png\')">详细定义</a>', "英文", "含义", "数值"]
		}, {
			"key": "dependedBy",
			"name": ["B(n)", "dependedBy", "被直接依赖模块个数"]
		}, {
			"key": "dependedBy_indirect",
			"name": ["B_I(n)", "dependedBy_indirect", "被间接依赖模块个数"]
		}, {
			"key": "dependedBy_total",
			"name": ["B_T(n)", "dependedBy_total", "被依赖模块总个数"]
		}, {
			"key": "dependedBy_depth",
			"name": ["B_D", "dependedBy_depth", "被依赖深度"]
		}, {
			"key": "dependedBy_external",
			"name": ["B_e(n)", "dependedBy_external", "被其它部件依赖模块个数"]
		}, {
			"key": "dependedBy_internal",
			"name": ["B_n(n)", "dependedBy_internal", "被本部件依赖模块个数"]
		}, {
			"key": "chipsetsdk_dependedBy",
			"name": ["被芯片组件模块依赖个数"]
		}, {
			"key": "platformsdk_dependedBy",
			"name": ["被NAPI模块依赖个数"]
		}]
	},
	"symbols_info": {
		"name": "符号信息",
		"rows": [{
			"name": ['<a href="javascript:fnShowHelpInfo(\'symbols.png\')">详细定义</a>', "英文", "含义", "数值"]
		}, {
			"key": "provided",
			"name": ["S_P(n)", "provided", "提供的符号个数"]
		}, {
			"key": "used",
			"name": ["S_Pt(n)", "truely provided", "被使用到的符号个数"]
		}, {
			"key": "unused",
			"name": ["S_Pf(n)", "falsely provided", "未被使用到的符号个数"]
		}, {
			"key": "needed",
			"name": ["S_U(n)", "undefined", "未定义符号个数"]
		}, {
			"key": "matched",
			"name": ["S_Ut(n)", "matched undefined", "与依赖库匹配的未定义符号个数"]
		}, {
			"key": "unmatched",
			"name": ["S_P(n)", "unmatched undefined", "与依赖库无法匹配的未定义符号个数"]
		}, {
			"key": "duplicated",
			"name": ["S_Uf(n)", "duplicates", "与依赖库匹配的重复未定义符号个数"]
		}, {
			"key": "external_symbols",
			"name": "跨部件被调用的符号个数"
		}, {
			"key": "chipsetsdk_symbols",
			"name": "被芯片组件模块调用的符号个数"
		}, {
			"key": "platformsdk_symbols",
			"name": "被NAPI模块调用的符号个数"
		}]
	}
};

var service_details_dict = {
	"basic_info": {
		"name": "服务基础信息",
		"rows": [{
			"name": ["配置字段", "字段说明", "默认值", "配置值"]
		}, {
			"key": "name",
			"name": ["name", "服务名称", "必配置项"]
		}, {
			"key": "path",
			"name": ["path", "当前服务的可执行文件全路径和参数，数组形式", "必配置项"]
		}, {
			"key": "uid",
			"name": ["uid", "当前服务进程的uid值", "0"]
		}, {
			"key": "gid",
			"name": ["gid", "当前服务进程的gid值", "0"]
		}, {
			"key": "once",
			"name": ["once", "当前服务进程是否为一次性进程", "0"]
		}, {
			"key": "console",
			"name": ["console", "是否控制台服务", "0"]
		}, {
			"key": "on_demand",
			"name": ["ondemand", "按需启动服务的标志", "0"]
		}, {
			"key": "start_mode",
			"name": ["start-mode", "服务的启动模式", "normal"]
		}, {
			"key": "sandbox",
			"name": ["sandbox", "是否沙盒运行", "0"]
		}, {
			"key": "critical_enable",
			"name": ["critical", "系统关键服务,在限定时间内服务重启次数达到限定值将导致系统重启", "0"]
		}, {
			"key": "critical_cfg",
			"name": "关键服务重启策略"
		}, {
			"key": "importance",
			"name": ["importance", "服务进程优先级", "0"]
		}, {
			"key": "cpu_core",
			"name": ["cpucore", "服务绑核信息", "[]"]
		}, {
			"key": "write_pid",
			"name": ["writepid", "保存服务pid文件列表", "[]"]
		}, {
			"key": "d_caps",
			"name": ["d-caps", "服务是否具备分布式能力", "0"]
		}]
	},
	"secure_info": {
		"name": "服务安全信息",
		"rows": [{
			"key": "caps",
			"name": ["caps", "服务进程拥有的系统能力", "[]"]
		}, {
			"key": "permission",
			"name": "permission"
		}, {
			"key": "permission_acls",
			"name": "permission_acls"
		}, {
			"key": "apl",
			"name": ["apl", "服务能力特权级别", "system_basic"]
		}, {
			"key": "secon",
			"name": ["secon", "服务MAC策略", "u:r:limit_domain:s0"]
		}]
	},
	"jobs_info": {
		"name": "服务关联jobs",
		"rows": [{
			"key": "boot_job",
			"name": ["on-boot", "系统启动时执行的jobs", ""]
		}, {
			"key": "start_job",
			"name": ["on-start", "服务启动时执行的jobs", ""]
		}, {
			"key": "stop_job",
			"name": ["on-stop", "服务退出时执行的jobs", ""]
		}, {
			"key": "restart_job",
			"name": ["on-restart", "服务重启时执行的jobs", ""]
		}]
	},
	"socket_info": {
		"name": "服务关联socket",
		"rows": [{
			"name": ["配置字段", "字段说明", "默认值", "配置socket数量"]
		}, {
			"key": "socket_num",
			"name": ["socket", "1. init进程在pre-fork阶段为socket类进程创建好socket,init进程中监听创建好的socket上的读写事件。\
			2. socket上有读写事件后,init进程拉起socket进程对应的native服务,并取消对socket的监听,将socket交由相应的native服务管理。\
			3. native服务无报文处理后,可以自动退出。init进程在回收子进程时会根据服务配置重新监听socket", "[]"]
		}]
	}
};

var service_socket_details_dict = {
	"basic_info": {
		"name": "服务配置socket信息",
		"rows": [{
			"name": ["配置字段", "字段说明", "默认值", "配置值"]
		}, {
			"key": "name",
			"name": ["name", "socket名称", "必配置项"]
		}, {
			"key": "family",
			"name": ["family", "socket协议族", "必配置项"]
		}, {
			"key": "type",
			"name": ["type", "socket协议类型", "必配置项"]
		}, {
			"key": "uid",
			"name": ["uid", "socket所属用户id", "必配置项"]
		}, {
			"key": "gid",
			"name": ["gid", "socket所属组id", "必配置项"]
		}, {
			"key": "option",
			"name": ["option", "socket功能选项", "0"]
		}, {
			"key": "protocol",
			"name": ["protocol", "socket协议编号", "必配置项"]
		}, {
			"key": "permissions",
			"name": ["permissions", "socket拥有的权限", "必配置项"]
		}]
	}
}

function fnGetModuleCmdUrl(module, id, cmd, args) {
	prefix = fnGetProductRestPrefix();

	// Handle different resource types for FastAPI version
	if (module === "startup_configs/" || module === "parameters/") {
		// Special handling for startup configs and parameters
		resource_type = module.slice(0, -1); // Remove trailing slash
		url = prefix + resource_type + "/" + id + "/" + cmd;
	} else {
		// Default handling
		url = prefix + module + id + "/" + cmd;
	}

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function generateServiceDetailValue(category, key, moduleId, moduleData) {
	if (key === "critical_cfg") {
		if (moduleData["critical_enable"] == 1) {
			critical_cfg = "";
			limit_time = moduleData["limit_time"];
			limit_count = moduleData["limit_count"];
			return limit_time.toString() + "秒内重启" + limit_count.toString() + "次，将重启设备";
		} else {
			return "非critical应用";
		}
	} else if (key === "path") {
		return moduleData[key].replace(/@/g, " ");
	} else if (key === "permission" || key === "gid" || key === "caps" || key === "permission_acls" || key === "write_pid") {
		return moduleData[key].replace(/@/g, "\n");
	} else if (key === "apl") {
		if (moduleData[key] === "") {
			return "system_basic";
		}
	} else if (category === "socket_info") {
		if (moduleData[key] > 0) {
			return  '<a href="javascript:fnShowServiceSocketDetails(\'' + moduleId + '\')">' + moduleData[key] + '</a>';
		}
	}
	return moduleData[key];
}

function __generateDetailValue(category, key, moduleId, moduleData) {
	if (key === "dependedBy_depth") { // No link
		return moduleData[key];
	}
	if (key === "processes") {
		if (moduleData[key] > 0) {
			return '<a href="javascript:fnEvtShowProcessTables(' + moduleId + ')">' + humanFileSize(moduleData[key]) + '</a>';
		}
	} else if (key === "modGroup") {
		return '<a href="javascript:fnShowHelpInfo(\'groups.png\')">' + groupDict[moduleData[key]] + '</a>';
	} else if ((key === "depth") && (moduleData[key] > 0)) {
		return '<a href="' + fnGetModulesRestUrl(moduleId, "fields", {"type":key, "format":"png"}) +'" target="_blank">' + moduleData[key] + '<a/>';
	} else if ((category === "deps_info") || (category === "dependedBy_info")) {
		if (moduleData[key] > 0) {
			return  '<a href="javascript:fnEvtShowDepsTables(' + moduleId + ', \'' + key + '\')">' + moduleData[key] + '</a>';
		}
	} else if (category === "symbols_info") {
		if (moduleData[key] > 0) {
			return  '<a href="javascript:fnEvtShowCallTables(' + moduleId + ', \'' + key + '\')">' + moduleData[key] + '</a>';
		}
	} else if (category === "resource_info") {
		return humanFileSize(moduleData[key]);
	} else if (category === "basic_info") {
		if (key === "sa_id") {
			return moduleData[key];
		}
		if (key === "chipset") {
			if (moduleData[key] === "0") {
				return "系统组件";
			}
			return "芯片组件";
		}
		if (moduleData[key] === "0") {
			return "否";
		} else if (moduleData[key] === "1") {
			return "是";
		} else if (key === "hdiType") {
			if (moduleData[key] in hdiTypeDict) {
				return hdiTypeDict[moduleData[key]];
			}
			return "NA";
		}
	}
	return moduleData[key];
}

function generateParamCollapse(parent, show, moduleData) {
	var header = '<div class="card">';
	// collapse content div
	header += '<div id="collapse_' + "name" + '" class="collapse ' + show + '" aria-labelledby="heading' + "name" + '" data-parent="#' + parent + '">';
	header += '<div class="container">';
	paramInfo = {"prefix": "参数前缀", "type": "类型", "dacUser": "参数所属用户", "dacGroup": "参数所属组", "dacMode": "权限", "selinuxLabel": "selinux标签", "value": "值"};
	for (var key in paramInfo) {
		header += '<div class="row border-bottom">';
		header += '<div class="col border-end">' + paramInfo[key] + '</div>';
		if (key == "dacUser" && moduleData["data"][0][key] == "") {
			header += '<div class="col text-end">' + "root" + '</div>';
		} else if (key == "dacGroup" && moduleData["data"][0][key] == "") {
			header += '<div class="col text-end">' + "root" + '</div>';
		} else if (key == "dacMode" && moduleData["data"][0][key] == "0") {
			header += '<div class="col text-end">' + "774" + '</div>';
		} else if (key == "selinuxLabel" && moduleData["data"][0][key] == "") {
			header += '<div class="col text-end">' + "u:object_r:default_param:s0" + '</div>';
		} else {
			header += '<div class="col text-end">' + moduleData["data"][0][key] + '</div>';	
		}
		header += '</div>';
	}
	header += '</div>';
	header += '</div>';
	header += '</div>';
	return header;
}

function generateJobCollapse(parent, show, moduleData, jobId) {
	var header = '<div class="card">';
	// collapse content div
	header += '<div id="collapse_' + "name" + '" class="collapse ' + show + '" aria-labelledby="heading' + "name" + '" data-parent="#' + parent + '">';
	header += '<div class="container">';
	header += '<div class="row border-bottom">';
	header += '<div class="col border-end">' + "启动服务命令" + '</div>';
	header += '<div class="col text-left">' + "服务名称" + '</div>';
	header += '</div>';
	for (var key in moduleData["data"]) {
		header += '<div class="row border-bottom">';
		header += '<div class="col border-end">' + moduleData["data"][key]["name"] + '</div>';;
		header += '<div class="col text-left">' + moduleData["data"][key]["content"] + '</div>';
		header += '</div>';
	}
	header += '</div>';
	header += '</div>';
	header += '</div>';
	return header;
}

function generateStartServiceCollapse(parent, show, moduleData) {
	var header = '<div class="card">';
	// collapse content div
	header += '<div id="collapse_' + "name" + '" class="collapse ' + show + '" aria-labelledby="heading' + "name" + '" data-parent="#' + parent + '">';
	header += '<div class="container">';
	header += '<div class="row border-bottom">';
	header += '<div class="col border-end">' + "命令名称" + '</div>';
	header += '<div class="col text-left">' + "命令参数" + '</div>';	
	header += '</div>';
	for (var key in moduleData["data"]) {
		header += '<div class="row border-bottom">';
		header += '<div class="col border-end">' + moduleData["data"][key]["name"] + '</div>';
		header += '<div class="col text-left">' + moduleData["data"][key]["content"] + '</div>';	
		header += '</div>';
	}
	header += '</div>';
	header += '</div>';
	header += '</div>';
	return header;
}

function generateParamForm(parent, show, moduleData) {
	header = '<form class="row g-3" id="add-key-form" action="" method="get">';
	header += '<div class="mb-3 row">';
	header += '<label for="serviceInputDac" class="col-sm-2 col-form-label">service name</label>';
	header += '<div class="col-sm-10">';
	header += '<input type="text" maxlength="4096" class="form-control" id="serviceInputDac" placeholder="service name">';
	header += '</div>';
	header += '</div>';
	header += '<div class="mb-3 row">';
	header += '<label for="paramInput" class="col-sm-2 col-form-label">param prefix</label>';
	header += '<div class="col-sm-10">';
	header += '<input type="text" maxlength="4096" class="form-control" id="paramInput" placeholder="const.example">';
	header += '</div>';
	header += '</div>';
	header += '<div class="col-auto">';
	header += '<button type="button" id="btn_submit" class="btn btn-primary mb-3">check</button>';
	header += '</div>';
	header += '</form>';
	header += '<div>PARAM DAC 权限</div>';
	header += '<div id="dac_res"></div>';
	header += '<div>PARAM MAC 策略</div>';
	header += '<div id="mac_res"></div>';
	header += '<div>service拥有的DAC权限</div>';
	header += '<div id="service_dac_res"></div>';

	return header;
}

function genCheckButton()
{
	var options = ["read", "write", "watcher"];
	var title = ["请选择用户拥有的权限", "请选择组拥有的权限", "请选择其他用户拥有的权限"];
	var header = "";
	var id = 1;
	for (var start = 0; start <= 2; start++) {
		header += '<h6 style="color:#0000FF">' + title[start] + '</h6>';
		for(var i = 0; i < 3; i++) {
			header += '<div class="form-check form-check-inline">';
			header += '<input class="form-check-input" type="checkbox" id="inlineCheckbox' + id.toString() + '" value="1">';
			header += '<label class="form-check-label" for="inlineCheckbox' + i.toString() + '" >' + options[i] + '</label>';
			header += '</div>';
			id++;
		}
	}
	return header;
}

function generateParamconfigForm(parent, show, moduleData)
{
	header = '<form class="row g-3" id="add-key-form" action="" method="get">';
	header += '<div class="mb-3 row">';
	header += '<label for="param_input" class="col-sm-2 col-form-label">新增参数名</label>';
	header += '<div class="col-sm-10">';
	header += '<input type="text" maxlength="4096" class="form-control" id="param_input" placeholder="const.example">';
	header += '</div>';
	header += '</div>';
	header += '<div class="mb-3 row">';
	header += '<label for="serviceInput" class="col-sm-2 col-form-label">使用该参数的服务名</label>';
	header += '<div class="col-sm-10">';
	header += '<input type="text" maxlength="4096" class="form-control" id="serviceInput" placeholder="service name">';
	header += '</div>';
	header += '</div>';

	header += '<div>';
	header += genCheckButton();
	header += '</div>';

	header += '<div class="col-auto">';
	header += '<button type="button" id="btn_submit_config" class="btn btn-primary mb-3">submit</button>';
	header += '</div>';
	header += '</form>';
	header += '<div  style="color:#FF0000;font-weight:bolder">DAC 权限配置</div>';
	header += '<div id="dac_res_cfg"></div>';
	header += '<div id="dac_res_cfg1"></div>';
	header += '<div id="dac_res_cfg2"></div>';
	header += '<div id="dac_res_cfg3"></div>';
	header += '<div style="color:#FF0000;font-weight:bolder">MAC 策略配置</div>';

	header += '<div id="mac_res_cfg0" style="color:#00FF00">selinux标签定义</div>';
	header += '<div id="mac_res_cfg01"></div>';
	header += '<div id="mac_res_cfg02"></div>';

	header += '<div id="mac_res_cfg" style="color:#00FF00">selinux给init授权</div>';
	header += '<div id="mac_res_cfg1"></div>';
	header += '<div id="mac_res_cfg2"></div>';
	header += '<div id="mac_res_cfg31" style="color:#00FF00">selinux设置写权限</div>';
	header += '<div id="mac_res_cfg3"></div>';
	header += '<div id="mac_res_cfg41" style="color:#00FF00">selinux设置读权限</div>';
	header += '<div id="mac_res_cfg4"></div>';
	header += '<div id="mac_res_cfg51" style="color:#00FF00">selinux设置watcher权限</div>';
	header += '<div id="mac_res_cfg5"></div>';
	header += '<div id="mac_res_cfg6"></div>';
	header += '<div id="mac_res_cfg7"></div>';
	header += '<div id="mac_res_cfg8"></div>';

	return header;
}

function getDacMode(binDacStr)
{
	var num = 0;
	for(var i = 0; i < binDacStr.length; i++){
		num = num * 2 + (binDacStr[i] - '0');
	}
	return num;
}

function getResCfgStr(data, dacMode, inputParam)
{
	dac_cfg_str = "";
	service_user = getParamInfo(data, "uid");
	service_group = getParamInfo(data, "gid");
	service_group = service_group.substring(0, service_group.indexOf('@') != -1 ? service_group.indexOf('@'): service_group.length);
	dac_cfg_str += inputParam + " = " + service_user + ":" + service_group + ":" + "0" + getDacMode(dacMode).toString(8);
	return dac_cfg_str;
}

function getRealCon(con)
{
	realCon = con.substring(0, con.lastIndexOf(":"));
	return realCon.substring(realCon.lastIndexOf(":") + 1, realCon.length);
}

function setMacCfg(param, paramCon, serviceCon)
{
	realParamCon = paramCon;
	realServiceCon = getRealCon(serviceCon);
	selinuxConDef1 = param + " u:object_r:" + realParamCon + ":s0";
	selinuxConDef2 = "type " + realParamCon + ", parameter_attr;";
	mac_res_cfg_str1 = "allow " + realParamCon + " tmpfs:filesystem associate;";
	mac_res_cfg_str2 = "allow init " + " " + realParamCon + ":file { map open read relabelto relabelfrom };";
	mac_res_cfg_str3 = "allow " + realServiceCon + " " + realParamCon + ":parameter_service { set };";
	mac_res_cfg_str4 = "allow " + realServiceCon + " " + realParamCon + ":file { map open read };";
	if (realServiceCon == "param_watcher") {
		mac_res_cfg_str6 = "param_wather can't watch itself";
		mac_res_cfg_str7 = "";
		mac_res_cfg_str8 = "";
	} else {
		mac_res_cfg_str6 = "allow param_watcher " + realServiceCon + ":binder { call };";
		mac_res_cfg_str7 = "allow " + realServiceCon + " " + "param_watcher:binder { call transfer };";
		mac_res_cfg_str8 = "allow" + " " + realServiceCon + " " + "sa_param_watcher:samgr_class { get };";
	}
	document.getElementById("mac_res_cfg01").innerText = selinuxConDef1;
	document.getElementById("mac_res_cfg02").innerText = selinuxConDef2;
	document.getElementById("mac_res_cfg1").innerText = mac_res_cfg_str1;
	document.getElementById("mac_res_cfg2").innerText = mac_res_cfg_str2;
	document.getElementById("mac_res_cfg3").innerText = mac_res_cfg_str3;
	document.getElementById("mac_res_cfg4").innerText = mac_res_cfg_str4;
	document.getElementById("mac_res_cfg6").innerText = mac_res_cfg_str6;
	document.getElementById("mac_res_cfg7").innerText = mac_res_cfg_str7;
	document.getElementById("mac_res_cfg8").innerText = mac_res_cfg_str8;
}

function clearInfo()
{
	document.getElementById("mac_res_cfg01").innerText = "";
	document.getElementById("mac_res_cfg02").innerText = "";
	document.getElementById("mac_res_cfg1").innerText = "";
	document.getElementById("mac_res_cfg2").innerText = "";
	document.getElementById("mac_res_cfg3").innerText = "";
	document.getElementById("mac_res_cfg4").innerText = "";
	document.getElementById("mac_res_cfg6").innerText = "";
	document.getElementById("mac_res_cfg7").innerText = "";
	document.getElementById("mac_res_cfg8").innerText = "";
}

function generateServiceCollapse(parent, name, info, show, moduleId, moduleData, button) {
	var header = '<div class="card">';

	// Header div
	header += '<div class="card-header" id="heading' + name + '">';
	header += '<h5 class="mb-0">';
	header += '<button class="btn btn-link" id="collapse_btn_' + name + '">';
	header += button + '</button>';
	header += '</h5>';
	header += '</div>';

	// collapse content div
	header += '<div id="collapse_' + name + '" class="collapse ' + show + '" aria-labelledby="heading' + name + '" data-parent="#' + parent + '">';
	header += '<div class="container">';

	info["rows"].forEach(function (val, idx, arr) {
		header += '<div class="row border-bottom">';
		if (Array.isArray(val["name"])) {
			val["name"].forEach(function (subName, subIdx, subArr) {
				header += '<div class="col border-end">' + subName + '</div>';
			});
		} else {
			header += '<div class="col border-end">' + val["name"] + '</div>';
		}
		if ("key" in val) {
			header += '<div class="col text-end">' + generateServiceDetailValue(name, val["key"], moduleId, moduleData) + '</div>';
		}
		header += '</div>';
	});

	header += '</div>';
	header += '</div>';
	header += '</div>';
	return header;
}

function addServiceCollapseClickFunc() {
	for (var collaps in service_details_dict) {
		$("#collapse_btn_"+collaps).unbind ('click').click(collaps, function (evt) {
			$("#collapse_"+evt.data).toggle();
		});
	}
}

function addSocketCollapseClickFunc(collaps, s) {
	for (var i = 1; i < s; i++) {
		$("#collapse_btn_" + collaps + i.toString()).unbind ('click').click(collaps + i.toString(), function (evt) {
			$("#collapse_"+evt.data).toggle();
		});
	}
}

function fnShowServiceDetails(moduleId) {
	$.get(fnGetModuleCmdUrl("startup_configs/", moduleId, "details", {"format":"json"}), function (data, status) {
		createDialogWithTable("service_dialog");
		var detailHtml = "";
		var show = "show";
		for (var collaps in service_details_dict) {
			detailHtml += generateServiceCollapse("accordion", collaps, service_details_dict[collaps], show,
			moduleId, JSON.parse(data)["data"][0], service_details_dict[collaps]["name"]);
			show = "hide";
		}
		$("#accordion_service_dialog").html(detailHtml);
		$('#service_dialog').appendTo("body").modal("show");
		addServiceCollapseClickFunc();
	});
}

function fnShowServiceSocketDetails(moduleId) {
	$.get(fnGetModuleCmdUrl("startup_configs/", moduleId, "socket", {"format":"json"}), function (data, status) {
		createDialogWithTable("service_socket_dialog");
		var detailHtml = "";
		var show = "show";
		var s = 1;
		for (var i of JSON.parse(data)["data"]) {
			for (var collaps in service_socket_details_dict) {
				detailHtml += generateServiceCollapse("accordion", collaps + s.toString(),
				service_socket_details_dict[collaps], show, moduleId, i, service_socket_details_dict[collaps]["name"] + s.toString());
				show = "hide";
			}
			s++;
		}
		$("#accordion_service_socket_dialog").html(detailHtml);
		$('#service_socket_dialog').appendTo("body").modal("show");
		addSocketCollapseClickFunc("basic_info", s);
	});
}

function fnGetParamDetails(param) {
	$.get(fnGetModuleCmdUrl("parameters/", 1, "details", {"format":"json", "param": param}), function (data, status) {
		createDialogWithTable("param_dialog");
		var show = "show";
		detailHtml = generateParamCollapse("accordion", show, JSON.parse(data));
		$("#accordion_param_dialog").html(detailHtml);
		$('#param_dialog').appendTo("body").modal("show");
	});
}

function createStageCmdDialogHeader(dialogId, jobId) {
	var content = '<div class="modal-header">\n';
	content += '<h5 class="modal-title">' + jobId + tableOptions[dialogId]["title"] + '</h5>\n';
	content += '<button type="button" class="close" data-dismiss="dialog" aria-label="Close" id="' + dialogId + '_close_btn"value="' + dialogId + '">\n';
	content += '<span aria-hidden="true">&times;</span>\n';
	content += '</button>\n';
	content += '</div>\n';
	return content;
}

function createStageCmdDialogWithTable(dialogId, jobId) {
	if (!(dialogId in tableOptions)) {
		return;
	}

	var content = _createDialogDiv(dialogId);
	content += '<div class="modal-content">\n';

	// Header
	content += createStageCmdDialogHeader(dialogId, jobId);

	// Body
	content += '<div class="modal-body">\n';

	//   wrapper item
	content += _createWrapperBlock(dialogId);

	content += '</div>\n';

	// Footer
	content += '<div class="modal-footer">\n';
	content += '</div>\n';

	content += '</div>\n';
	content += '</div>\n';

	$("#"+dialogId).html(content);

	$("#"+dialogId+"_close_btn").click(function(evt) {
		var dialogId = $(evt.target).parent().val();
		$("#"+dialogId).modal("hide");
	});
}

function fnGetJobDetails(jobId) {
	$.get(fnGetModuleCmdUrl("startup_configs/", jobId, "cmdNum", {"format":"json"}), function (data, status) {
		createStageCmdDialogWithTable("stage_cmd_dialog", jobId);
		var show = "show";
		detailHtml = generateJobCollapse("accordion", show, JSON.parse(data), jobId);
		$("#accordion_stage_cmd_dialog").html(detailHtml);
		$('#stage_cmd_dialog').appendTo("body").modal("show");
	});
}

function fnGetStartServiceDetails(jobId) {
	$.get(fnGetModuleCmdUrl("startup_configs/", jobId, "StartServiceNum", {"format":"json"}), function (data, status) {
		createStageCmdDialogWithTable("stage_service_dialog", jobId);
		var show = "show";
		detailHtml = generateStartServiceCollapse("accordion", show, JSON.parse(data));
		$("#accordion_stage_service_dialog").html(detailHtml);
		$('#stage_service_dialog').appendTo("body").modal("show");
	});
}

function _generateCollapse(parent, name, info, show, moduleId, moduleData) {
	var header = '<div class="card">';

	// Header div
	header += '<div class="card-header" id="heading' + name + '">';
	header += '<h5 class="mb-0">';
	header += '<button class="btn btn-link" id="collapse_btn_' + name + '">';
	header += info["name"] + '</button>';
	header += '</h5>';
	header += '</div>';

	// collapse content div
	header += '<div id="collapse_' + name + '" class="collapse ' + show + '" aria-labelledby="heading' + name + '" data-parent="#' + parent + '">';
	header += '<div class="container">';

	info["rows"].forEach(function (val, idx, arr) {
		header += '<div class="row border-bottom">';
		if (Array.isArray(val["name"])) {
			val["name"].forEach(function (subName, subIdx, subArr) {
				header += '<div class="col border-end">' + subName + '</div>';
			});
		} else {
			header += '<div class="col border-end">' + val["name"] + '</div>';
		}
		if ("key" in val) {
			header += '<div class="col text-end">' + __generateDetailValue(name, val["key"], moduleId, moduleData) + '</div>';
		}
		header += '</div>';
	});

	header += '</div>';
	header += '</div>';

	header += '</div>';
	return header;
}

function _addCollapseClickFunc() {
	for (var collaps in details_dict) {
		$("#collapse_btn_"+collaps).unbind ('click').click(collaps, function (evt) {
			$("#collapse_"+evt.data).toggle();
		});
	}
}

function fnShowModuleDetails(moduleId) {
	$.get(fnGetModulesRestUrl(moduleId, "details", {"format":"json"}), function (data, status) {
		createDialogWithTable("module_dialog");
		var detailHtml = "";
		var show = "show";
		for (var collaps in details_dict) {
			detailHtml += _generateCollapse("accordion", collaps, details_dict[collaps], show, moduleId, JSON.parse(data));
			show = "hide";
		}
		$("#accordion").html(detailHtml);
		$('#module_dialog').appendTo("body").modal("show");
		_addCollapseClickFunc();
	});
}

var moduleTable;

function loadModules() {
	let symbol_table = new DataTable('#symbol_table', {
	});

	$('#all_modules').click(function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"format":"xml"}));
	});

	moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("modules"),
		"sScrollX": "1000px",
		//"sScrollY": "400px",
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [0,1],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			fnModuleCommonRowCallback(aData, nRow);

			pos = 4;
			var link = '<a href="javascript:fnShowModuleDetails(' + aData[0] + ")\">" + aData[pos] + '</a>';
			var ele = 'td:eq(' + (pos-2).toString() + ')';
			$(ele, nRow).html(link);

			$('td:eq(3)', nRow).text(groupDict[aData[5]]);

			var startIdx = 7;
			["deps", "deps_external", "deps_internal", "deps_indirect", "deps_total", "dependedBy", "dependedBy_external", "dependedBy_internal", "dependedBy_indirect", "dependedBy_total"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowDepsTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos-2).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			startIdx = 18;
			["provided", "used", "unused", "needed", "matched", "duplicated", "unmatched"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowCallTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos-2).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			pos = 28;
			if (aData[pos] > 0) {
				var link = '<a href="javascript:fnEvtShowProcessTables(' + aData[1] + ")\">" + aData[pos] + '</a>';
				var ele = 'td:eq(' + (pos-2).toString() + ')';
				$(ele, nRow).html(link);
			}

			var module_id = aData[0];

			/* Depth link */
			dataToLink = aData[6];
			$('td:eq(4)', nRow).html('<a href="' + fnGetModulesRestUrl(module_id, "fields", {"type":"depth", "format":"png"}) +'" target="_blank">' + dataToLink + '<a/>');

			/* Human readble size */
			$('td:eq(24)', nRow).text( humanFileSize(aData[26]) );
			$('td:eq(25)', nRow).text( humanFileSize(aData[27]) );

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable, function (selectedData) {
		fnEvtFuncCallGraph(selectedData);
	});
	createDynamicFilterFooters(moduleTable);
	createStaticFilterFooters(moduleTable);
}

/*
 * Components related API
 */
function fnEvtFuncComponentsCallGraph(rowData) {
	var module_id = rowData[0];

	xargs = {"type":"deps", "format":"svg"};
	$("#svg_callgraph").attr("data", fnGetComponentsRestUrl(module_id, "fields", xargs));
}

function fnGetComponentsRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix()
	url =  prefix + "components/" + id + "/" + cmd;

	if (args) {
		url = url + "?" + fnArgsToURI(args)
	}
	return url;
}

function fnComponentTableCommonProc(moduleTable) {
	$("#components tbody").on("click", "tr", function() {
		if ($(this).hasClass('selected')) {
			$(this).removeClass('selected');
		} else {
			moduleTable.$('tr.selected').removeClass('selected');
			$(this).addClass('selected');
		}

		fnEvtFuncComponentsCallGraph(moduleTable.fnGetData(this));
	});
}

function fnEvtShowModuleDepsForComponent(id, type) {
	/*var headers = [ "调用模块", "被调用模块", "调用次数" ];
	$('#depends thead tr th').each( function (idx, ele) {
		if (idx >= 1) {
			$(ele).text(headers[idx - 1]);
		}
	});*/

	createDialogWithTable("deps_dialog");

	url = fnGetComponentsRestUrl(id, "deps", {"type":type});
	var symbolTable = $('#depends').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"sScrollX": "1000px",
		"bPaginate": true,
		"bDestroy": true,
		"columnDefs": [{
			visible: false,
			targets: [0,1,2],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			/* Append the grade to the default row class name */
			dataToLink = aData[8];
			if (dataToLink > 0) {
				$('td:eq(5)', nRow).html( '<a href="javascript:fnEvtShowSymbolsForDeps(' + aData[0] + ')">' + dataToLink + '</a>' );
			}

			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[1] + '\')">' + aData[4] + '</a>';
			$('td:eq(1)', nRow).html(link);

			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[2] + '\')">' + aData[6] + '</a>';
			$('td:eq(3)', nRow).html(link);
			return nRow;
		}
	} );
	$('#download_xml_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "deps", {"type":type, "format":"xml"}));
	});
	$('#download_svg_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps_internal", "format":"svg"}));
	});
	$('#download_png_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps_internal", "format":"png"}));
	});
	$('#download_dot_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps_internal", "format":"dot"}));
	});
	$('#deps_dialog').appendTo("body").modal("show");
}

function fnEvtShowComponentDepsTables(id, type) {
	url = fnGetComponentsRestUrl(id, "deps", {"type":type});
	var symbolTable = $('#com_depends').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			/* Append the grade to the default row class name */
			dataToLink = aData[3];
			if (dataToLink > 0) {
				$('td:eq(3)', nRow).html( '<a href="javascript:fnEvtShowModuleDepsForComponent(' + aData[0] + ',\'dep\')">' + dataToLink + '</a>' );
			}
			return nRow;
		}
	} );
	$('#com_download_xml_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "deps", {"type":type, "format":"xml"}));
	});
	$('#com_download_svg_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps", "format":"svg"}));
	});
	$('#com_download_png_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps", "format":"png"}));
	});
	$('#com_download_dot_deps').unbind ('click').click(id, function (evt) {
		window.open(fnGetComponentsRestUrl(evt.data, "fields", {"type":"deps", "format":"dot"}));
	});
	$('#com_deps_dialog').appendTo("body").modal("show");
}

function loadComponents() {
	let symbol_table = new DataTable('#symbol_table', {
	});

	$('#all_components').click(function () {
		window.open(fnGetAllItemsFilterUrl("components", {"format":"xml"}));
	});

	var moduleTable = $('#components').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("components"),
		"sScrollX": "1000px",
		"bPaginate": true,
		"columnDefs": [{
				visible: false,
				target: 0,
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			/* Human readble size */
			$('td:eq(2)', nRow).text( humanFileSize(aData[3]) );
			$('td:eq(3)', nRow).text( humanFileSize(aData[4]) );
			$('td:eq(4)', nRow).text( humanFileSize(aData[5]) );

			var link = '<a href="' + fnGetStaticHtmlUrl("modules", undefined, undefined, {"componentName": aData[2]}) + '">' + aData[6] + '</a>';
			$('td:eq(5)', nRow).html(link);

			var startIdx = 7;
			["deps_internal"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowModuleDepsForComponent(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos-1).toString() + ')'
					$(ele, nRow).html(link);
				}
			});

			startIdx = 8;
			["deps", "dependedBy"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowComponentDepsTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos-1).toString() + ')'
					$(ele, nRow).html(link);
				}
			});
			return nRow;
		}
	} );

	fnComponentTableCommonProc(moduleTable);
}

function loadPlatformSDKModules() {
	let symbol_table = new DataTable('#symbol_table', {
	});

	$('#all_modules').click(function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"__category": "platformsdk", "format":"xml"}));
	});

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("modules", {"__category": "platformsdk"}),
		"bPaginate": true,
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var startIdx = 4;
			["deps", "deps_total", "dependedBy", "platformsdk_dependedBy"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowDepsTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			startIdx = 8;
			["provided", "used", "platformsdk_symbols"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowCallTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + pos.toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable, function (selectedData) {
		fnEvtFuncCallGraph(selectedData, "platformsdk");
	});
}

function loadChipsetSDKModules() {
	let symbol_table = new DataTable('#symbol_table', {
	});

	$('#all_modules').click(function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"__category": "chipsetsdk", "format":"xml"}));
	});
	$('#chipsetsdk_graph').click( function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"type":"chipsetsdk", "format":"svg"}));
	});
	$('#hdi_core_graph').click(function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"type":"hdi_core", "format":"svg"}));
	});

	//$("#hdi_core_graph").attr("data", fnGetModulesRestUrl(module_id, "fields", xargs));

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("modules", {"__category": "chipsetsdk"}),
		"bPaginate": true,
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var startIdx = 4;
			["deps", "deps_total", "dependedBy", "chipsetsdk_dependedBy"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowDepsTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			startIdx = 8;
			["provided", "used", "chipsetsdk_symbols"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowCallTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + pos.toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable, function (selectedData) {
		fnEvtFuncCallGraph(selectedData, "chipsetsdk");
	});
}

function loadInnerAPIModules() {
	let symbol_table = new DataTable('#symbol_table', {
	});

	$('#all_modules').click(function () {
		window.open(fnGetAllItemsFilterUrl("modules", {"__category": "innerapi", "format":"xml"}));
	});

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("modules", {"__category": "innerapi"}),
		"bPaginate": true,
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var startIdx = 4;
			["deps", "deps_total", "dependedBy", "dependedBy_total"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowDepsTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			startIdx = 8;
			["provided", "used", "external_symbols"].forEach(function (val, idx, arr) {
				pos = startIdx+idx;
				if (aData[pos] > 0) {
					var link = '<a href="javascript:fnEvtShowCallTables(' + aData[0] + ", '" + val + "')\">" + aData[pos] + '</a>';
					var ele = 'td:eq(' + (pos).toString() + ')';
					$(ele, nRow).html(link);
				}
			});

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable, function (selectedData) {
		fnEvtFuncCallGraph(selectedData, "dependedBy_external");
	});
}

function fnGetProcessesRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();
	url =  prefix + "processes/" + id + "/" + cmd;

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnEvtShowProcessObjectsTables(id) {
	createDialogWithTable("objects_dialog");

	url = fnGetProcessesRestUrl(id, "objects", {});
	var objectsTable = $("#objects_table").dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"sScrollX": "1000px",
		"sScrollY": "300px",
		"columnDefs": [{
			visible: false,
			targets: [0],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnEvtShowProcessVmasTables(' + aData[0] + ',\'object\')">' + aData[3] + '</a>';
			$('td:eq(2)', nRow).html(link);
			return nRow;
		}
	} );
	$('#download_xml_objects').unbind ('click').click(id, function (evt) {
		window.open(fnGetProcessesRestUrl(evt.data, "objects", {"format":"xml"}));
	});
	$("#objects_dialog").appendTo("body").modal("show");
}

function fnEvtShowProcessThreadsTables(id) {
	createDialogWithTable("threads_dialog");
	url = fnGetProcessesRestUrl(id, "threads", {});
	var objectsTable = $("#threads_table").dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"sScrollY": "300px"
	} );
	$('#download_xml_threads').unbind ('click').click(id, function (evt) {
		window.open(fnGetProcessesRestUrl(evt.data, "threads", {"format":"xml"}));
	});
	$("#threads_dialog").appendTo("body").modal("show");
}

function fnEvtShowProcessVmasTables(id, type) {
	createDialogWithTable("vmas_dialog");
	url = fnGetProcessesRestUrl(id, "vmas", {"type": type});
	var symbolTable = $("#vmas_table").dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"sScrollX": "1000px",
		"sScrollY": "300px",
		"columnDefs": [{
			visible: false,
			target: 0,
		}]
	} );
	$('#download_xml_vmas').unbind ('click').click(id, function (evt) {
		window.open(fnGetProcessesRestUrl(evt.data, "vmas", {"type": type, "format":"xml"}));
	});
	$("#vmas_dialog").appendTo("body").modal("show");
}

function loadProcesses() {
	$('#all_modules').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("processes", {"format":"xml"}));
	});
	$('#all_module_details').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("processes", {"format":"xml", "details": 1}));
	});

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("processes", {}),
		"sScrollX": "1000px",
		"pageLength": 15,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [ ],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnEvtShowProcessThreadsTables(' + aData[0] + ', \'process\')">' + aData[4] + '</a>';
			$('td:eq(4)', nRow).html(link);

			var link = '<a href="javascript:fnEvtShowProcessObjectsTables(' + aData[0] + ')">' + aData[5] + '</a>';
			$('td:eq(5)', nRow).html(link);

			var link = '<a href="javascript:fnEvtShowProcessVmasTables(' + aData[0] + ', \'process\')">' + aData[6] + '</a>';
			$('td:eq(6)', nRow).html(link);

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

function fnGetObjectsRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();
	url =  prefix + "objects/" + id + "/" + cmd;

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnEvtShowProcessTables(id) {
	createDialogWithTable("processes_dialog");

	url = fnGetObjectsRestUrl(id, "processes", {});
	var objectsTable = $("#processes_table").dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"sScrollX": "1000px",
		"sScrollY": "300px",
		"columnDefs": [{
			visible: false,
			targets: [0, 1]
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnEvtShowProcessVmasTables(' + aData[0] + ',\'object\')">' + aData[4] + '</a>';
			$('td:eq(2)', nRow).html(link);
			return nRow;
		}
	} );
	$('#download_xml_processes').unbind ('click').click(id, function (evt) {
		window.open(fnGetObjectsRestUrl(evt.data, "processes", {"format":"xml"}));
	});
	$("#processes_dialog").appendTo("body").modal("show");
}

function loadProcessObjects() {
	$('#all_modules').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("objects", {"format":"xml"}));
	});

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("objects", {}),
		"sScrollX": "1000px",
		"pageLength": 15,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			target: 0,
		}],
		"order": [[2, 'desc']],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnEvtShowProcessTables(' + aData[0] + ')">' + aData[2] + '</a>';
			$('td:eq(1)', nRow).html(link);

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

function fnGetThreadsRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();
	url =  prefix + "threads/" + id + "/" + cmd;

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnEvtShowThreadsByName(id) {
	createDialogWithTable("threads_dialog");
	url = fnGetThreadsRestUrl(id, "threads", {});
	var objectsTable = $("#threads_table").dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"sScrollY": "300px",
		"order": [[3, 'desc']],
	} );
	$('#download_xml_threads').unbind ('click').click(id, function (evt) {
		window.open(fnGetThreadsRestUrl(evt.data, "threads", {"format":"xml"}));
	});
	$("#threads_dialog").appendTo("body").modal("show");
}

function loadNamedThreads() {
	$('#all_modules').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("objects", {"format":"xml"}));
	});
	$('#all_module_details').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("objects", {"format":"xml", "details":1}));
	});

	// fnEvtShowProcessThreadsTables
	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("threads", {}),
		"pageLength": 15,
		"bPaginate": false,
		"order": [[1, 'desc']],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnEvtShowThreadsByName(\'' + aData[0] + '\')">' + aData[1] + '</a>';
			$('td:eq(1)', nRow).html(link);

			var link = '<a href="javascript:fnEvtShowThreadsByName(\'' + aData[0] + '\')">' + aData[2] + '</a>';
			$('td:eq(2)', nRow).html(link);

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

function fnGetSymbolsRestUrl(id, cmd, args) {
	prefix = fnGetProductRestPrefix();
	url =  prefix + "symbols/" + id + "/" + cmd;

	if (args) {
		url = url + "?" + fnArgsToURI(args);
	}
	return url;
}

function fnEvtShowCallDetailsBySymbolId(id) {
	createDialogWithTable("symbol_calls_details");

	var url = fnGetSymbolsRestUrl(id, "details");
	var symbolTable = $('#symbol_calls_details_table').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"columnDefs": [{
			visible: false,
			targets: [0,1,2,3,4],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[1] + '\')">' + aData[5] + '</a>';
			$('td:eq(0)', nRow).html(link);

			link = '<a href="javascript:fnShowModuleDetails(\'' + aData[2] + '\')">' + aData[6] + '</a>';
			$('td:eq(1)', nRow).html(link);

			return nRow;
		}
	} );
	$('#download_xml_symbol_calls_details').unbind ('click').click(id, function (evt) {
		window.open(fnGetSymbolsRestUrl(evt.data, "details", {"format":"xml"}));
	});
	$('#symbol_calls_details').appendTo("body").modal("show");
}

function fnEvtShowCallsCntBySymbolName(id, type) {
	createDialogWithTable("symbol_calls_cnt");

	var url = fnGetSymbolsRestUrl(id, type);
	var symbolTable = $('#symbol_calls_cnt_table').dataTable( {
		"bProcessing": true,
		"sAjaxSource": url,
		"bDestroy": true,
		"columnDefs": [{
			visible: false,
			targets: [0,1,2,3],
		}],
		"order": [[5, 'desc']],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var link = '<a href="javascript:fnShowModuleDetails(\'' + aData[1] + '\')">' + aData[4] + '</a>';
			$('td:eq(0)', nRow).html(link);

			if (aData[5] > 0) {
				var link = '<a href="javascript:fnEvtShowCallDetailsBySymbolId(\'' + aData[0] + '\')">' + aData[5] + '</a>';
				$('td:eq(1)', nRow).html(link);
			}

			return nRow;
		}
	} );
	$('#download_xml_symbol_calls_cnt').unbind ('click').click(id, function (evt) {
		window.open(fnGetSymbolsRestUrl(evt.data, type, {"format":"xml"}));
	});
	$('#symbol_calls_cnt').appendTo("body").modal("show");
}

function loadDuplicatedSymbols() {
	$('#all_modules').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("symbols", {"format":"xml"}));
	});
	$('#all_module_details').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("symbols", {"format":"xml", "details":1}));
	});

	var moduleTable = $('#dup_symbols').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("symbols", {}),
		"pageLength": 15,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [0],
		}],
		"order": [[1, 'desc']],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			if (aData[1] > 0) {
				var link = '<a href="javascript:fnEvtShowCallsCntBySymbolName(\'' + aData[0] + '\', \'modules\')">' + aData[1] + '</a>';
				$('td:eq(0)', nRow).html(link);
			}

			if (aData[2] > 0) {
				var link = '<a href="javascript:fnEvtShowCallsCntBySymbolName(\'' + aData[0] + '\', \'calls\')">' + aData[2] + '</a>';
				$('td:eq(1)', nRow).html(link);
			}

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

function  createSearchedSymbolsTable() {
	$("#search_symbols_div").html('<div class="btn-group me-2 float-end">\n' +
				'<button type="button" id="all_modules" class="btn btn-sm btn-outline-secondary">XML下载</button>\n' +
			'</div>\n' +
			'<table cellpadding="0" cellspacing="0" border="0" class="display" id="search_symbols">\n' +
			'<thead>\n' +
				'<tr>\n' +
					'<th>原名</th>\n' +
					'<th style="text-align: center;" class="show_in_line table_header_second">定义次数</th>\n' +
					'<th style="text-align: center;" class="show_in_line table_header_second">被调用次数</th>\n' +
					'<th style="text-align: center;" class="show_in_line table_header_second">符号名称</th>\n' +
				'</tr>\n' +
			'</thead>\n' +
			'<tbody>\n' +
			'</tbody>\n' +
			'</table>\n');
}

function searchSymbol() {
	createSearchedSymbolsTable();

	var searchStr = $("#search_symbol_text").val();
	var url = fnGetSymbolsRestUrl(searchStr, "search", {"format": "xml"});
	$('#all_modules').unbind ('click').click(function () {
		window.open(url);
	});

	var moduleTable = $('#search_symbols').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetSymbolsRestUrl(searchStr, "search"),
		"pageLength": 15,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [0],
		}],
		"order": [[1, 'desc']],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			if (aData[1] > 0) {
				var link = '<a href="javascript:fnEvtShowCallsCntBySymbolName(\'' + aData[0] + '\', \'modules\')">' + aData[1] + '</a>';
				$('td:eq(0)', nRow).html(link);
			}

			if (aData[2] > 0) {
				var link = '<a href="javascript:fnEvtShowCallsCntBySymbolName(\'' + aData[0] + '\', \'calls\')">' + aData[2] + '</a>';
				$('td:eq(1)', nRow).html(link);
			}

			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

function getParamInfo(data, key) {
	if (!data["data"][0]) {
		return;
	}
	return data["data"][0][key];
}

function getDacLimitstr(dac, paramGroup, serviceGroups)
{
	var permissionDac = ["read", "write", "watcher"];
	var binDacStr = parseInt(dac, 8).toString(2);
	var dacString = "";
	for (var i = 0; i < 3 && i < binDacStr.length; i++) {
		if (binDacStr[i] == '1') {
			dacString += permissionDac[i];
			dacString += " ";
		} else if (binDacStr[i] == '0' && i == 1) {
			if (checkServiceGroupHasParamGroup(paramGroup, serviceGroups) == 1) {
				dacString += permissionDac[i];
				dacString += " ";
			}
		}
	}
	if (dacString == "") {
		dacString += "Without any permissions";
	}
	return dacString;
}

function checkServiceUserInParamGroup(serviceUser, groupUsers)
{
	while (groupUsers.indexOf('@') != -1) {
		user = groupUsers.substring(0, service_group.indexOf('@'));
		if (user == serviceUser) {
			return 1;
		}
		groupUsers = groupUsers.substring(service_group.indexOf('@'), service_group.length);
	}
	return 0;
}

function checkServiceGroupHasParamGroup(paramGroup, serviceGroups)
{
	let groupArray = serviceGroups.split("@");
	for (item of groupArray) {
		if (paramGroup == item) {
			return 1;
		}
	}
	return 0;
}

function getServiceLimitsStr(data)
{
	dac_cfg_str1 = "service 属于: ";
	service_groups = getParamInfo(data, "serviceGid");
	var dacMode = parseInt(data["data"][0]["dacMode"] == "0"? "774" : data["data"][0]["dacMode"], 8);
	service_group = service_groups.substring(0, service_groups.indexOf('@') == -1 ? service_groups.length : service_groups.indexOf('@'));
	relation = "其他用户";
	if (getParamInfo(data, "serviceUid") == getParamInfo(data, "dacUser")) {
		relation = "同用户";
		dac_limits = getDacLimitstr(dacMode.toString(8)[0], getParamInfo(data, "dacGroup"), service_groups);
	} else if (getParamInfo(data, "dacGroup") == service_group) {
		relation = "同组";
		dac_limits = getDacLimitstr(dacMode.toString(8)[1], getParamInfo(data, "dacGroup"), service_groups);
	} else if (checkServiceUserInParamGroup(getParamInfo(data, "serviceUid"), getParamInfo(data, "userNames")) != 0) {
		relation = "同组";
		dac_limits = getDacLimitstr(dacMode.toString(8)[1], getParamInfo(data, "dacGroup"), service_groups);
	} else {
		dac_limits = getDacLimitstr(dacMode.toString(8)[2], getParamInfo(data, "dacGroup"), service_groups);
	}
	dac_cfg_str1 += relation + " | ";
	if (getParamInfo(data, "serviceUid") == "root") {
		dac_cfg_str1 += "当前拥有权限： " + "read write watcher";
	} else {
		dac_cfg_str1 += "当前拥有权限： " + dac_limits;
	}
	return dac_cfg_str1;
}

// for system parameters
function loadSystemParameters() {
	// 下载系统参数配置
	$('#download_parameters').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("parameters", {"format":"xml"}));
	});
	// 检查系统参数权限
	$('#check_parameters').unbind ('click').click(function () {
		createDialogWithTable("param_limits_dialog");
		detailHtml = generateParamForm();
		$("#accordion_limits_dialog").html(detailHtml);
		$('#param_limits_dialog').appendTo("body").modal("show");
		$('#param_limits_dialog').on('hidden', function() { 
			$('param_limits_dialog').val(null); 
		});
		$('#btn_submit').click(function() {
			if (!document.getElementById('paramInput').value || !document.getElementById('serviceInputDac').value) {
				document.getElementById("dac_res").innerText = "please input param";
			} else {
				$.get(fnGetModuleCmdUrl("parameters/", "2", "checkServiceDac", {"format":"json", "param":document.getElementById('paramInput').value,
					"service":document.getElementById('serviceInputDac').value}), function (data, status) {
					var paramPrefix = getParamInfo(JSON.parse(data), "paramPrefix");
					var serviceName = getParamInfo(JSON.parse(data), "serviceName");
					if (paramPrefix == "" || serviceName == "") {
						document.getElementById("dac_res").innerText = "no such param or service";
						document.getElementById("mac_res").innerText = "no such param or service";
						document.getElementById("service_dac_res").innerText = "";
					} else {
						serviceLimits = getServiceLimitsStr(JSON.parse(data));
						dacMode = getParamInfo(JSON.parse(data), "dacMode");
						var dacString = "";
						var macString = "selinuxLabel: ";
						dacUser = "dacUser: " + (getParamInfo(JSON.parse(data), "dacUser") ? getParamInfo(JSON.parse(data), "dacUser") : "root");
						dacGroup = "dacGroup: " + (getParamInfo(JSON.parse(data), "dacGroup") ? getParamInfo(JSON.parse(data), "dacGroup") : "root");
						dacString += dacUser + " " + dacGroup + " " + "dacMode: " + (dacMode == "0" ? "774" : dacMode);
						macString += getParamInfo(JSON.parse(data), "selinuxLabel") ? getParamInfo(JSON.parse(data), "selinuxLabel") : "u:object_r:default_param:s0";
						document.getElementById("dac_res").innerText = dacString;
						document.getElementById("mac_res").innerText = macString;
						document.getElementById("service_dac_res").innerText = serviceLimits;
					}
				});
			}
		});
	});
	// 系统参数配置
	$('#mac_config').unbind ('click').click(function () {
		createDialogWithTable("param_config_dialog");
		detailHtml = generateParamconfigForm();
		$("#accordion_config_dialog").html(detailHtml);
		$('#param_config_dialog').appendTo("body").modal("show");
		$('#param_config_dialog').on('hidden', function() { 
			$('param_config_dialog').val(null); 
		});
		$('#btn_submit_config').click(function() {
			dacMode = "";
			for (var i = 1; i <= 9; i++) {
				if ( document.getElementById('inlineCheckbox' + i.toString()).checked ) {
					dacMode += document.getElementById('inlineCheckbox' + i.toString()).value;
				} else {
					dacMode += "0";
				}
			}
			inputParam = document.getElementById('param_input').value;
			if (!inputParam || !document.getElementById('serviceInput').value) {
				document.getElementById("dac_res_cfg").innerText = "please input param and service name";
				clearInfo();
			} else {
				$.get(fnGetModuleCmdUrl("parameters/", "1", "Getconfig", {"format":"json", "param":inputParam,
					"service":document.getElementById('serviceInput').value}), function (data, status) {
					var serviceName = getParamInfo(JSON.parse(data), "name");
					if (!serviceName) {
						document.getElementById("dac_res_cfg").innerText = "no such service";
						clearInfo();
					} else {
						paramCon = serviceName + "_param";
						serviceCon = getParamInfo(JSON.parse(data), "secon");
						dac_res_cfg_str = getResCfgStr(JSON.parse(data), dacMode, inputParam);
						document.getElementById("dac_res_cfg").innerText = dac_res_cfg_str;
						setMacCfg(inputParam, paramCon, serviceCon);
					}
				});
			}
		});
	} );

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("parameters", {}),
		"pageLength": 10,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [ ],
		}],
		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var paramPrefix = "'" + aData[0] + "'"
			var link = '<a href="javascript:fnGetParamDetails(' + paramPrefix + ")\">" + aData[0] + '</a>';
			$('td:eq(0)', nRow).html(link);
			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

// for system startup config
function loadStartupConfigs() {
	$('#download_service').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("startup_configs", {"format":"xml"}));
	});

	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("startup_configs", {}),
		"sScrollX": "1000px",
		"pageLength": 10,
		"bPaginate": true,
		"columnDefs": [{
			visible: false,
			targets: [ ],
		}],
		"fnRowCallback": function(nRow, aData, iDisplayIndex) {
			for (var i = 0; i < 7; i++) {
				link = '<a href="javascript:fnShowServiceDetails(\'' + aData[0] + "\')\">" + aData[i].replace(/@/g, "\n\r") + '</a>';
				var ele = 'td:eq(' + (i).toString() + ')';
				$(ele, nRow).html(link);
			}
			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}

// for system startup config
function loadStartupConfigJobs() {
	$('#all_download').unbind ('click').click(function () {
		window.open(fnGetAllItemsFilterUrl("startup_configs", {"format":"xml", "config-type": "jobs"}));
	});
	var moduleTable = $('#modules').dataTable( {
		"bProcessing": true,
		"sAjaxSource": fnGetAllItemsFilterUrl("startup_configs", {"config-type": "jobs"}),
		"pageLength": 10,
		"bPaginate": true,
		"bSort":false,

		"fnRowCallback": function( nRow, aData, iDisplayIndex ) {
			var jobId = "'" + aData[0] + "'"
			var link = '<a href="javascript:fnGetJobDetails(' + jobId + ")\">" + aData[1] + '</a>';
			$('td:eq(1)', nRow).html(link);
			link = '<a href="javascript:fnGetStartServiceDetails(' + jobId + ")\">" + aData[2] + '</a>';
			$('td:eq(2)', nRow).html(link);
			return nRow;
		}
	} );

	fnModuleTableCommonProc(moduleTable);
}